import { BaseSystem } from '../base';
import { EVENTS, type IEventBus } from '../../events';
import type { PlayerStateSystem } from '../player-state';
import {
  SKILL_MASTERY_LEVEL_MAP,
  type CultivationSkillItemConfig,
  type CultivationSkillLevelConfig,
} from '../../data/item/type';
import { CultivationSkillModel, RealmModel } from '../../model';
import { MODEL_NAME } from '../../constants/model-names';
import type { CultivationSkillUpgradeProgressInfo } from '../../model/cultivation-skill/type';

export class CultivationSkillSystem extends BaseSystem {
  private bus: IEventBus;
  private playerStateSystem: PlayerStateSystem;

  constructor(bus: IEventBus, playerStateSystem: PlayerStateSystem) {
    super();
    this.bus = bus;
    this.playerStateSystem = playerStateSystem;

    this.bus.on(EVENTS.CULTIVATION_SKILL_SET_MAIN_CULTIVATION_SKILL, (id) => {
      const cultivationSkillModel =
        this.playerStateSystem.getModel<CultivationSkillModel>(
          MODEL_NAME.CULTIVATION_SKILL
        );
      if (!cultivationSkillModel.isLearned(id)) return;
      cultivationSkillModel.setMainCultivationSkill(id);
    });

    this.bus.on(EVENTS.CULTIVATION_SKILL_UPGRADE, (id) => {
      const cultivationSkillModel =
        this.playerStateSystem.getModel<CultivationSkillModel>(
          MODEL_NAME.CULTIVATION_SKILL
        );
      const realmModel = this.playerStateSystem.getModel<RealmModel>(
        MODEL_NAME.REALM
      );
      const skill = cultivationSkillModel.getPlayerSkill(id);
      if (!skill) return;
      const skillConfig = cultivationSkillModel.getItemConfig(id);
      if (!skillConfig) return;
      const levelConfig = skillConfig.levels[skill.currentLevel - 1];
      let canUpgradeImmediately = false;
      if (!levelConfig) {
        canUpgradeImmediately = true;
      } else {
        canUpgradeImmediately = this.canBreakthroughSkill(levelConfig);
      }
      if (!canUpgradeImmediately) return;
      realmModel.consumeExp(levelConfig?.requiredExp || 0);
      cultivationSkillModel.upgradeSkill(id);
      cultivationSkillModel.resetCultivationSkillProgress(id);
      this.updateUpgradeInfo();
      this.bus.emit(EVENTS.CULTIVATION_SKILL_UPGRADE_SUCCESS);
    });

    this.bus.on(EVENTS.CULTIVATION_SKILL_UPDATE_UPGRADE_INFO, () => {
      this.updateUpgradeInfo();
    });
    this.bus.on(EVENTS.CULTIVATION_COMPLETED, () => {
      this.updateUpgradeInfo();
    });
  }

  public canBreakthroughSkill(levelConfig: CultivationSkillLevelConfig) {
    const realmModel = this.playerStateSystem.getModel<RealmModel>(
      MODEL_NAME.REALM
    );
    const conditions = levelConfig.breakthroughCondition || [];
    const currentRealmExp = realmModel.getState().currentExp;
    if (currentRealmExp < levelConfig.requiredExp) return false;
    return this.playerStateSystem.checkConditions(conditions);
  }

  public override init(): void {
    this.updateUpgradeInfo();
  }

  private updateUpgradeInfo() {
    const cultivationSkillModel =
      this.playerStateSystem.getModel<CultivationSkillModel>(
        MODEL_NAME.CULTIVATION_SKILL
      );
    if (!cultivationSkillModel) return;
    const skills = cultivationSkillModel.getPlayerSkillsInfo();
    const result: CultivationSkillUpgradeProgressInfo[] = [];
    skills.forEach((info) => {
      const { skill, skillConfig } = info;
      let levelConfig = skillConfig.levels[skill.currentLevel - 1];
      if (skillConfig.maxLevel < skill.currentLevel) {
        levelConfig = skillConfig.levels[skillConfig.maxLevel - 1];
        skill.currentLevel = skillConfig.maxLevel;
      }
      if (levelConfig) {
        const condition = levelConfig.breakthroughCondition || [];
        const progressInfo =
          this.playerStateSystem.getConditionsProgress(condition);
        const isMaxLevel = skill.currentLevel >= skillConfig.maxLevel;
        const cumulativeSpeedBonus = this.calculateCumulativeSpeedBonus(
          skillConfig,
          skill.currentLevel
        );
        result.push({
          ...info,
          skillUpgradeInfo: progressInfo,
          isMaxLevel,
          masteryLevelDisplayName:
            SKILL_MASTERY_LEVEL_MAP[levelConfig.masteryLevel],
          cumulativeSpeedBonus,
        });
      }
    });
    cultivationSkillModel.setCultivationSkillUpgradeProgressInfo(result);
  }

  private calculateCumulativeSpeedBonus(
    skillConfig: CultivationSkillItemConfig,
    currentLevel: number
  ): number {
    let cumulativeBonus = 0;

    // 累加从1级到当前等级的所有 cultivationSpeedBonus
    for (let i = 0; i < currentLevel; i++) {
      const levelConfig = skillConfig.levels[i];
      if (levelConfig) {
        cumulativeBonus += levelConfig.cultivationSpeedBonus;
      }
    }

    return cumulativeBonus;
  }
}
